home *** CD-ROM | disk | FTP | other *** search
/ Kit PC World De Ampliacion De Windows 95 / Kit PC World de ampliacion de Windows 95.iso / internet / sweeper / samples / olecon~1 / framewrk / ctlmisc.cpp < prev    next >
Text File  |  1995-12-02  |  42KB  |  1,463 lines

  1. //=--------------------------------------------------------------------------=
  2. // ControlMisc.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright  1995  Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // things that aren't elsewhere, such as property pages, and connection
  13. // points.
  14. //
  15. #include "IPServer.H"
  16. #include "CtrlObj.H"
  17. #include "CtlHelp.H"
  18. #include "Globals.H"
  19. #include "StdEnum.H"
  20. #include "Util.H"
  21.  
  22. #include <stdarg.h>
  23.  
  24. // for ASSERT and FAIL
  25. //
  26. SZTHISFILE
  27.  
  28. // this is used in our window proc so that we can find out who was last created
  29. //
  30. static COleControl *s_pLastControlCreated;
  31.  
  32. //=--------------------------------------------------------------------------=
  33. // COleControl::COleControl
  34. //=--------------------------------------------------------------------------=
  35. // constructor
  36. //
  37. // Parameters:
  38. //    IUnknown *          - [in] controlling Unknown
  39. //    int                 - [in] type of primary dispatch interface OBJECT_TYPE_*
  40. //    void *              - [in] pointer to entire object
  41. //
  42. // Notes:
  43. //
  44. COleControl::COleControl
  45. (
  46.     IUnknown *pUnkOuter,
  47.     int       iPrimaryDispatch,
  48.     void     *pMainInterface
  49. )
  50. : CAutomationObject(pUnkOuter, iPrimaryDispatch, pMainInterface),
  51.   m_cpEvents(SINK_TYPE_EVENT),
  52.   m_cpPropNotify(SINK_TYPE_PROPNOTIFY)
  53. {
  54.     // initialize all our variables -- we decided against using a memory-zeroing
  55.     // memory allocator, so we sort of have to do this work now ...
  56.     //
  57.     m_nFreezeEvents = 0;
  58.  
  59.     m_pClientSite = NULL;
  60.     m_pControlSite = NULL;
  61.     m_pInPlaceSite = NULL;
  62.     m_pInPlaceFrame = NULL;
  63.     m_pInPlaceUIWindow = NULL;
  64.  
  65.     // certain hosts don't like 0,0 as your initial size, so we're going to set
  66.     // our initial size to 100,50 [so it's at least sort of visible on the screen]
  67.     //
  68.     m_Size.cx = 100;
  69.     m_Size.cy = 50;
  70.  
  71.     m_hwnd = NULL;
  72.     m_hwndParent = NULL;
  73.     m_hwndReflect = NULL;
  74.     m_fHostReflects = TRUE;
  75.     m_fCheckedReflecting = FALSE;
  76.  
  77.     m_dwWindowStyle = 0;
  78.     m_dwWindowExStyle = 0;
  79.     m_szWindowTitle = NULL;
  80.  
  81.     m_cAccel = 0;
  82.     m_hAccel = NULL;
  83.     m_nFreezeEvents = 0;
  84.     m_pSimpleFrameSite = NULL;
  85.     m_pOleAdviseHolder = NULL;
  86.     m_pViewAdviseSink = NULL;
  87.     m_pDispAmbient = NULL;
  88.  
  89.     m_fDirty = FALSE;
  90.     m_fModeFlagValid = FALSE;
  91.     m_fInPlaceActive = FALSE;
  92.     m_fInPlaceVisible = FALSE;
  93.     m_fUIActive = FALSE;
  94.     m_fSaveSucceeded = FALSE;
  95.     m_fViewAdvisePrimeFirst = FALSE;
  96.     m_fViewAdviseOnlyOnce = FALSE;
  97.     m_fRunMode = FALSE;
  98. }
  99.  
  100. //=--------------------------------------------------------------------------=
  101. // COleControl::~COleControl
  102. //=--------------------------------------------------------------------------=
  103. // "We are all of us resigned to death; it's life we aren't resigned to."
  104. //    - Graham Greene (1904-91)
  105. //
  106. // Notes:
  107. //
  108. COleControl::~COleControl()
  109. {
  110.     // if we've still got a window, go and kill it now.
  111.     //
  112.     if (m_hwnd) {
  113.         // so our window proc doesn't crash.
  114.         //
  115.         SetWindowLong(m_hwnd, GWL_USERDATA, 0xFFFFFFFF);
  116.         DestroyWindow(m_hwnd);
  117.     }
  118.  
  119.     if (m_hwndReflect) {
  120.         SetWindowLong(m_hwndReflect, GWL_USERDATA, 0);
  121.         DestroyWindow(m_hwndReflect);
  122.     }
  123.  
  124.     // clean up all the pointers we're holding around.
  125.     //
  126.     RELEASE_OBJECT(m_pClientSite);
  127.     RELEASE_OBJECT(m_pControlSite);
  128.     RELEASE_OBJECT(m_pInPlaceSite);
  129.     RELEASE_OBJECT(m_pInPlaceFrame);
  130.     RELEASE_OBJECT(m_pInPlaceUIWindow);
  131.     RELEASE_OBJECT(m_pSimpleFrameSite);
  132.     RELEASE_OBJECT(m_pOleAdviseHolder);
  133.     RELEASE_OBJECT(m_pViewAdviseSink);
  134.     RELEASE_OBJECT(m_pDispAmbient);
  135. }
  136.  
  137. #ifndef DEBUG
  138. #pragma optimize("t", on)
  139. #endif // DEBUG
  140.  
  141. //=--------------------------------------------------------------------------=
  142. // COleControl::InternalQueryInterface
  143. //=--------------------------------------------------------------------------=
  144. // derived-controls should delegate back to this when they decide to support
  145. // additional interfaces
  146. //
  147. // Parameters:
  148. //    REFIID        - [in]  interface they want
  149. //    void **       - [out] where they want to put the resulting object ptr.
  150. //
  151. // Output:
  152. //    HRESULT       - S_OK, E_NOINTERFACE
  153. //
  154. // Notes:
  155. //    - NOTE: this function is speed critical!!!!
  156. //
  157. HRESULT COleControl::InternalQueryInterface
  158. (
  159.     REFIID riid,
  160.     void **ppvObjOut
  161. )
  162. {
  163.     switch (riid.Data1) {
  164.         // private interface for prop page support
  165.         case Data1_IControlPrv:
  166.           if(DO_GUIDS_MATCH(riid, IID_IControlPrv)) {
  167.             *ppvObjOut = (void *)this;
  168.             ExternalAddRef();
  169.             return S_OK;
  170.           }
  171.           goto NoInterface;
  172.         QI_INHERITS(this, IOleControl);
  173.         QI_INHERITS(this, IOleObject);
  174.         QI_INHERITS((IPersistStorage *)this, IPersist);
  175.         QI_INHERITS(this, IPersistStreamInit);
  176.         QI_INHERITS(this, IOleInPlaceObject);
  177.         QI_INHERITS((IOleInPlaceActiveObject *)this, IOleWindow);
  178.         QI_INHERITS(this, IOleInPlaceActiveObject);
  179.         QI_INHERITS(this, IViewObject);
  180.         QI_INHERITS(this, IViewObject2);
  181.         QI_INHERITS(this, IConnectionPointContainer);
  182.         QI_INHERITS(this, ISpecifyPropertyPages);
  183.         QI_INHERITS(this, IPersistStorage);
  184.         QI_INHERITS(this, IPersistPropertyBag);
  185.         QI_INHERITS(this, IProvideClassInfo);
  186.         default:
  187.             goto NoInterface;
  188.     }
  189.  
  190.     // we like the interface, so addref and return
  191.     //
  192.     ((IUnknown *)(*ppvObjOut))->AddRef();
  193.     return S_OK;
  194.  
  195.   NoInterface:
  196.     // delegate to super-class for automation interfaces, etc ...
  197.     //
  198.     return CAutomationObject::InternalQueryInterface(riid, ppvObjOut);
  199. }
  200.  
  201. #ifndef DEBUG
  202. #pragma optimize("s", on)
  203. #endif // DEBUG
  204.  
  205. //=--------------------------------------------------------------------------=
  206. // COleControl::FindConnectionPoint    [IConnectionPointContainer]
  207. //=--------------------------------------------------------------------------=
  208. // given an IID, find a connection point sink for it.
  209. //
  210. // Parameters:
  211. //    REFIID              - [in]  interfaces they want
  212. //    IConnectionPoint ** - [out] where the cp should go
  213. //
  214. // Output:
  215. //    HRESULT
  216. //
  217. // Notes:
  218. //
  219. STDMETHODIMP COleControl::FindConnectionPoint
  220. (
  221.     REFIID             riid,
  222.     IConnectionPoint **ppConnectionPoint
  223. )
  224. {
  225.     CHECK_POINTER(ppConnectionPoint);
  226.  
  227.     // we support the event interface, and IDispatch for it, and we also
  228.     // support IPropertyNotifySink.
  229.     //
  230.     if (DO_GUIDS_MATCH(riid, EVENTIIDOFCONTROL(m_ObjectType)) || DO_GUIDS_MATCH(riid, IID_IDispatch))
  231.         *ppConnectionPoint = &m_cpEvents;
  232.     else if (DO_GUIDS_MATCH(riid, IID_IPropertyNotifySink))
  233.         *ppConnectionPoint = &m_cpPropNotify;
  234.     else
  235.         return E_NOINTERFACE;
  236.  
  237.     // generic post-processing.
  238.     //
  239.     (*ppConnectionPoint)->AddRef();
  240.     return S_OK;
  241. }
  242.  
  243. //=--------------------------------------------------------------------------=
  244. // COleControl::EnumConnectionPoints    [IConnectionPointContainer]
  245. //=--------------------------------------------------------------------------=
  246. // creates an enumerator for connection points.
  247. //
  248. // Parameters:
  249. //    IEnumConnectionPoints **    - [out]
  250. //
  251. // Output:
  252. //    HRESULT
  253. //
  254. // Notes:
  255. //
  256. STDMETHODIMP COleControl::EnumConnectionPoints
  257. (
  258.     IEnumConnectionPoints **ppEnumConnectionPoints
  259. )
  260. {
  261.     IConnectionPoint **rgConnectionPoints;
  262.  
  263.     CHECK_POINTER(ppEnumConnectionPoints);
  264.  
  265.     // HeapAlloc an array of connection points [since our standard enum
  266.     // assumes this and HeapFree's it later ]
  267.     //
  268.     rgConnectionPoints = (IConnectionPoint **)HeapAlloc(g_hHeap, 0, sizeof(IConnectionPoint *) * 2);
  269.     RETURN_ON_NULLALLOC(rgConnectionPoints);
  270.  
  271.     // we support the event interface for this dude as well as IPropertyNotifySink
  272.     //
  273.     rgConnectionPoints[0] = &m_cpEvents;
  274.     rgConnectionPoints[1] = &m_cpPropNotify;
  275.  
  276.     *ppEnumConnectionPoints = (IEnumConnectionPoints *)(IEnumGeneric *) new CStandardEnum(IID_IEnumConnectionPoints,
  277.                                 2, sizeof(IConnectionPoint *), (void *)rgConnectionPoints,
  278.                                 CopyAndAddRefObject);
  279.     if (!*ppEnumConnectionPoints) {
  280.         HeapFree(g_hHeap, 0, rgConnectionPoints);
  281.         return E_OUTOFMEMORY;
  282.     }
  283.  
  284.     return S_OK;
  285. }
  286.  
  287. //=--------------------------------------------------------------------------=
  288. // COleControl::GetPages    [ISpecifyPropertyPages]
  289. //=--------------------------------------------------------------------------=
  290. // returns a counted array with the guids for our property pages.
  291. //
  292. // parameters:
  293. //    CAUUID *    - [out] where to put the counted array.
  294. //
  295. // Output:
  296. //    HRESULT
  297. //
  298. // NOtes:
  299. //
  300. STDMETHODIMP COleControl::GetPages
  301. (
  302.     CAUUID *pPages
  303. )
  304. {
  305.     const GUID **pElems;
  306.     void *pv;
  307.     WORD  x;
  308.  
  309.     // if there are no property pages, this is actually pretty easy.
  310.     //
  311.     if (!CPROPPAGESOFCONTROL(m_ObjectType)) {
  312.         pPages->cElems = 0;
  313.         pPages->pElems = NULL;
  314.         return S_OK;
  315.     }
  316.  
  317.     // fill out the Counted array, using IMalloc'd memory.
  318.     //
  319.     pPages->cElems = CPROPPAGESOFCONTROL(m_ObjectType);
  320.     pv = CoTaskMemAlloc(sizeof(GUID) * (pPages->cElems));
  321.     RETURN_ON_NULLALLOC(pv);
  322.     pPages->pElems = (GUID *)pv;
  323.  
  324.     // loop through our array of pages and get 'em.
  325.     //
  326.     pElems = PPROPPAGESOFCONTROL(m_ObjectType);
  327.     for (x = 0; x < pPages->cElems; x++)
  328.         pPages->pElems[x] = *(pElems[x]);
  329.  
  330.     return S_OK;
  331. }
  332.  
  333. //=--------------------------------------------------------------------------=
  334. // COleControl::CConnectionPoint::m_pOleControl
  335. //=--------------------------------------------------------------------------=
  336. // returns a pointer to the control in which we are nested.
  337. //
  338. // Output:
  339. //    COleControl *
  340. //
  341. // Notes:
  342. //
  343. inline COleControl *COleControl::CConnectionPoint::m_pOleControl
  344. (
  345.     void
  346. )
  347. {
  348.     return (COleControl *)((BYTE *)this - ((m_bType == SINK_TYPE_EVENT)
  349.                                           ? offsetof(COleControl, m_cpEvents)
  350.                                           : offsetof(COleControl, m_cpPropNotify)));
  351. }
  352.  
  353. //=--------------------------------------------------------------------------=
  354. // COleControl::CConnectionPoint::QueryInterface
  355. //=--------------------------------------------------------------------------=
  356. // standard qi
  357. //
  358. // Parameters:
  359. //    REFIID        - [in]  interface they want
  360. //    void **       - [out] where they want to put the resulting object ptr.
  361. //
  362. // Output:
  363. //    HRESULT       - S_OK, E_NOINTERFACE
  364. //
  365. // Notes:
  366. //
  367. STDMETHODIMP COleControl::CConnectionPoint::QueryInterface
  368. (
  369.     REFIID riid,
  370.     void **ppvObjOut
  371. )
  372. {
  373.     if (DO_GUIDS_MATCH(riid, IID_IConnectionPoint) || DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  374.         *ppvObjOut = (IConnectionPoint *)this;
  375.         AddRef();
  376.         return S_OK;
  377.     }
  378.  
  379.     return E_NOINTERFACE;
  380. }
  381.  
  382. //=--------------------------------------------------------------------------=
  383. // COleControl::CConnectionPoint::AddRef
  384. //=--------------------------------------------------------------------------=
  385. //
  386. // Output:
  387. //    ULONG        - the new reference count
  388. //
  389. // Notes:
  390. //
  391. ULONG COleControl::CConnectionPoint::AddRef
  392. (
  393.     void
  394. )
  395. {
  396.     return m_pOleControl()->ExternalAddRef();
  397. }
  398.  
  399. //=--------------------------------------------------------------------------=
  400. // COleControl::CConnectionPoint::Release
  401. //=--------------------------------------------------------------------------=
  402. //
  403. // Output:
  404. //    ULONG         - remaining refs
  405. //
  406. // Notes:
  407. //
  408. ULONG COleControl::CConnectionPoint::Release
  409. (
  410.     void
  411. )
  412. {
  413.     return m_pOleControl()->ExternalRelease();
  414. }
  415.  
  416. //=--------------------------------------------------------------------------=
  417. // COleControl::CConnectionPoint::GetConnectionInterface
  418. //=--------------------------------------------------------------------------=
  419. // returns the interface we support connections on.
  420. //
  421. // Parameters:
  422. //    IID *        - [out] interface we support.
  423. //
  424. // Output:
  425. //    HRESULT
  426. //
  427. // Notes:
  428. //
  429. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionInterface
  430. (
  431.     IID *piid
  432. )
  433. {
  434.     if (m_bType == SINK_TYPE_EVENT)
  435.         *piid = EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType);
  436.     else
  437.         *piid = IID_IPropertyNotifySink;
  438.  
  439.     return S_OK;
  440. }
  441.  
  442. //=--------------------------------------------------------------------------=
  443. // COleControl::CConnectionPoint::GetConnectionPointContainer
  444. //=--------------------------------------------------------------------------=
  445. // returns the connection point container
  446. //
  447. // Parameters:
  448. //    IConnectionPointContainer **ppCPC
  449. //
  450. // Output:
  451. //    HRESULT
  452. //
  453. // Notes:
  454. //
  455. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionPointContainer
  456. (
  457.     IConnectionPointContainer **ppCPC
  458. )
  459. {
  460.     return m_pOleControl()->ExternalQueryInterface(IID_IConnectionPointContainer, (void **)ppCPC);
  461. }
  462.  
  463.  
  464. //=--------------------------------------------------------------------------=
  465. // COleControl::CConnectiontPoint::Advise
  466. //=--------------------------------------------------------------------------=
  467. // someboyd wants to be advised when something happens.
  468. //
  469. // Parameters:
  470. //    IUnknown *        - [in]  guy who wants to be advised.
  471. //    DWORD *           - [out] cookie
  472. //
  473. // Output:
  474. //    HRESULT
  475. //
  476. // Notes:
  477. //
  478. STDMETHODIMP COleControl::CConnectionPoint::Advise
  479. (
  480.     IUnknown *pUnk,
  481.     DWORD    *pdwCookie
  482. )
  483. {
  484.     IUnknown **rgUnkNew;
  485.     HRESULT    hr;
  486.     void      *pv;
  487.     int        i = 0;
  488.  
  489.     CHECK_POINTER(pdwCookie);
  490.  
  491.     // first, make sure everybody's got what they thinks they got
  492.     //
  493.     if (m_bType == SINK_TYPE_EVENT) {
  494.  
  495.         // CONSIDER: 12.95 -- this theoretically is broken -- if they do a find
  496.         // connection point on IDispatch, and they just happened to also support
  497.         // the Event IID, we'd advise on that.  this is not awesome, but will
  498.         // prove entirely acceptable short term.
  499.         //
  500.         hr = pUnk->QueryInterface(EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType), &pv);
  501.         if (FAILED(hr))
  502.             hr = pUnk->QueryInterface(IID_IDispatch, &pv);
  503.     }
  504.     else
  505.         hr = pUnk->QueryInterface(IID_IPropertyNotifySink, &pv);
  506.     RETURN_ON_FAILURE(hr);
  507.  
  508.     // we optimize the case where there is only one sink to not allocate
  509.     // any storage.  turns out very rarely is there more than one.
  510.     //
  511.     switch (m_cSinks) {
  512.  
  513.         case 0:
  514.             ASSERT(!m_rgSinks, "Doh! this should be null when there are no sinks");
  515.             m_rgSinks = (IUnknown **)pv;
  516.             break;
  517.  
  518.         case 1:
  519.             // go ahead and do the initial allocation.  we'll get 8 at a time
  520.             //
  521.             rgUnkNew = (IUnknown **)HeapAlloc(g_hHeap, 0, 8 * sizeof(IUnknown *));
  522.             RETURN_ON_NULLALLOC(rgUnkNew);
  523.             rgUnkNew[0] = (IUnknown *)m_rgSinks;
  524.             rgUnkNew[1] = (IUnknown *)pv;
  525.             m_rgSinks = rgUnkNew;
  526.             break;
  527.  
  528.         default:
  529.             // if we're out of sinks, then we have to increase the size
  530.             // of the array
  531.             //
  532.             if (!(m_cSinks & 0x7)) {
  533.                 rgUnkNew = (IUnknown **)HeapReAlloc(g_hHeap, 0, m_rgSinks, (m_cSinks + 8) * sizeof(IUnknown *));
  534.                 RETURN_ON_NULLALLOC(rgUnkNew);
  535.                 m_rgSinks = rgUnkNew;
  536.             } else
  537.                 rgUnkNew = m_rgSinks;
  538.  
  539.             rgUnkNew[m_cSinks + 1] = (IUnknown *)pv;
  540.             break;
  541.     }
  542.  
  543.     *pdwCookie = (DWORD)pv;
  544.     m_cSinks++;
  545.     return S_OK;
  546. }
  547.  
  548. //=--------------------------------------------------------------------------=
  549. // COleControl::CConnectionPoint::Unadvise
  550. //=--------------------------------------------------------------------------=
  551. // they don't want to be told any more.
  552. //
  553. // Parameters:
  554. //    DWORD        - [in]  the cookie we gave 'em.
  555. //
  556. // Output:
  557. //    HRESULT
  558. //
  559. // Notes:
  560. //
  561. STDMETHODIMP COleControl::CConnectionPoint::Unadvise
  562. (
  563.     DWORD dwCookie
  564. )
  565. {
  566.     IUnknown *pUnk;
  567.     int       x;
  568.  
  569.     if (!dwCookie)
  570.         return S_OK;
  571.  
  572.     // see how many sinks we've currently got, and deal with things based
  573.     // on that.
  574.     //
  575.     switch (m_cSinks) {
  576.         case 1:
  577.             // it's the only sink.  make sure the ptrs are the same, and
  578.             // then free things up
  579.             //
  580.             if ((DWORD)m_rgSinks != dwCookie)
  581.                 return CONNECT_E_NOCONNECTION;
  582.             m_rgSinks = NULL;
  583.             break;
  584.  
  585.         case 2:
  586.             // there are two sinks.  go back down to one sink scenario
  587.             //
  588.             if ((DWORD)m_rgSinks[0] != dwCookie && (DWORD)m_rgSinks[1] != dwCookie)
  589.                 return CONNECT_E_NOCONNECTION;
  590.  
  591.             pUnk = ((DWORD)m_rgSinks[0] == dwCookie) ? m_rgSinks[1] : m_rgSinks[0];
  592.  
  593.             HeapFree(g_hHeap, 0, m_rgSinks);
  594.             m_rgSinks = (IUnknown **)pUnk;
  595.             break;
  596.  
  597.         default:
  598.             // there are more than two sinks.  just clean up the hole we've
  599.             // got in our array now.
  600.             //
  601.             for (x = 0; x < m_cSinks; x++) {
  602.                 if ((DWORD)m_rgSinks[x] == dwCookie)
  603.                     break;
  604.             }
  605.             if (x == m_cSinks) return CONNECT_E_NOCONNECTION;
  606.             memcpy(&(m_rgSinks[x]), &(m_rgSinks[x + 1]), (m_cSinks - x) * sizeof(IUnknown *));
  607.             break;
  608.     }
  609.  
  610.  
  611.     // we're happy
  612.     //
  613.     ((IUnknown *)dwCookie)->Release();
  614.     m_cSinks--;
  615.     return S_OK;
  616. }
  617.  
  618. //=--------------------------------------------------------------------------=
  619. // COleControl::CConnectionPoint::EnumConnections
  620. //=--------------------------------------------------------------------------=
  621. // enumerates all current connections
  622. //
  623. // Paramters:
  624. //    IEnumConnections ** - [out] new enumerator object
  625. //
  626. // Output:
  627. //    HRESULT
  628. //
  629. // NOtes:
  630. //
  631. STDMETHODIMP COleControl::CConnectionPoint::EnumConnections
  632. (
  633.     IEnumConnections **ppEnumOut
  634. )
  635. {
  636.     CONNECTDATA *rgConnectData = NULL;
  637.     int i;
  638.  
  639.     if (m_cSinks) {
  640.         // allocate some memory big enough to hold all of the sinks.
  641.         //
  642.         rgConnectData = (CONNECTDATA *)HeapAlloc(g_hHeap, 0, m_cSinks * sizeof(IUnknown *));
  643.         RETURN_ON_NULLALLOC(rgConnectData);
  644.  
  645.         // fill in the array
  646.         //
  647.         if (m_cSinks == 1) {
  648.             rgConnectData[0].pUnk = (IUnknown *)m_rgSinks;
  649.             rgConnectData[0].dwCookie = (DWORD)m_rgSinks;
  650.         } else {
  651.             // loop through all available sinks.
  652.             //
  653.             for (i = 0; i < m_cSinks; i++) {
  654.                 rgConnectData[i].pUnk = m_rgSinks[i];
  655.                 rgConnectData[i].dwCookie = (DWORD)m_rgSinks[i];
  656.             }
  657.         }
  658.     }
  659.  
  660.     // create yon enumerator object.
  661.     //
  662.     *ppEnumOut = (IEnumConnections *)(IEnumGeneric *)new CStandardEnum(IID_IEnumConnections,
  663.                         m_cSinks, sizeof(CONNECTDATA), rgConnectData, CopyAndAddRefObject);
  664.     if (!*ppEnumOut) {
  665.         HeapFree(g_hHeap, 0, rgConnectData);
  666.         return E_OUTOFMEMORY;
  667.     }
  668.  
  669.     return S_OK;
  670. }
  671.  
  672. //=--------------------------------------------------------------------------=
  673. // COleControl::CConnectionPoint::~CConnectionPoint
  674. //=--------------------------------------------------------------------------=
  675. // cleans up
  676. //
  677. // Notes:
  678. //
  679. COleControl::CConnectionPoint::~CConnectionPoint ()
  680. {
  681.     int x;
  682.  
  683.     // clean up some memory stuff
  684.     //
  685.     if (!m_cSinks)
  686.         return;
  687.     else if (m_cSinks == 1)
  688.         ((IUnknown *)m_rgSinks)->Release();
  689.     else {
  690.         for (x = 0; x < m_cSinks; x++)
  691.             RELEASE_OBJECT(m_rgSinks[x]);
  692.         HeapFree(g_hHeap, 0, m_rgSinks);
  693.     }
  694. }
  695.  
  696. //=--------------------------------------------------------------------------=
  697. // COleControl::CConnectionPiont::DoInvoke
  698. //=--------------------------------------------------------------------------=
  699. // fires an event to all listening on our event interface.
  700. //
  701. // Parameters:
  702. //    DISPID            - [in] event to fire.
  703. //    DISPPARAMS        - [in]
  704. //
  705. // Notes:
  706. //
  707. void COleControl::CConnectionPoint::DoInvoke
  708. (
  709.     DISPID      dispid,
  710.     DISPPARAMS *pdispparams
  711. )
  712. {
  713.     int iConnection;
  714.  
  715.     // if we don't have any sinks, then there's nothing to do.  we intentionally
  716.     // ignore errors here.
  717.     //
  718.     if (m_cSinks == 0)
  719.         return;
  720.     else if (m_cSinks == 1)
  721.         ((IDispatch *)m_rgSinks)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  722.     else
  723.         for (iConnection = 0; iConnection < m_cSinks; iConnection++)
  724.             ((IDispatch *)m_rgSinks[iConnection])->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  725. }
  726.  
  727. //=--------------------------------------------------------------------------=
  728. // COleControl::CConnectionPoint::DoOnChanged
  729. //=--------------------------------------------------------------------------=
  730. // fires the OnChanged event for IPropertyNotifySink listeners.
  731. //
  732. // Parameters:
  733. //    DISPID            - [in] dude that changed.
  734. //
  735. // Output:
  736. //    none
  737. //
  738. // Notes:
  739. //
  740. void COleControl::CConnectionPoint::DoOnChanged
  741. (
  742.     DISPID dispid
  743. )
  744. {
  745.     int iConnection;
  746.  
  747.     // if we don't have any sinks, then there's nothing to do.
  748.     //
  749.     if (m_cSinks == 0)
  750.         return;
  751.     else if (m_cSinks == 1)
  752.         ((IPropertyNotifySink *)m_rgSinks)->OnChanged(dispid);
  753.     else
  754.         for (iConnection = 0; iConnection < m_cSinks; iConnection++)
  755.             ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
  756. }
  757.  
  758. //=--------------------------------------------------------------------------=
  759. // COleControl::CConnectionPoint::DoOnRequestEdit
  760. //=--------------------------------------------------------------------------=
  761. // fires the OnRequestEdit for IPropertyNotifySinkListeners
  762. //
  763. // Parameters:
  764. //    DISPID             - [in] dispid user wants to change.
  765. //
  766. // Output:
  767. //    BOOL               - false means you cant
  768. //
  769. // Notes:
  770. //
  771. BOOL COleControl::CConnectionPoint::DoOnRequestEdit
  772. (
  773.     DISPID dispid
  774. )
  775. {
  776.     HRESULT hr;
  777.     int     iConnection;
  778.  
  779.     // if we don't have any sinks, then there's nothing to do.
  780.     //
  781.     if (m_cSinks == 0)
  782.         hr = S_OK;
  783.     else if (m_cSinks == 1)
  784.         hr =((IPropertyNotifySink *)m_rgSinks)->OnChanged(dispid);
  785.     else {
  786.         for (iConnection = 0; iConnection < m_cSinks; iConnection++) {
  787.             hr = ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
  788.             if (hr != S_OK) break;
  789.         }
  790.     }
  791.  
  792.     return (hr == S_OK) ? TRUE : FALSE;
  793. }
  794.  
  795. //=--------------------------------------------------------------------------=
  796. // COleControl::CreateInPlaceWindow
  797. //=--------------------------------------------------------------------------=
  798. // creates the window with which we will be working.
  799. // yay.
  800. //
  801. // Parameters:
  802. //    int            - [in] left
  803. //    int            - [in] top
  804. //
  805. // Output:
  806. //    HWND
  807. //
  808. // Notes:
  809. //
  810. HWND COleControl::CreateInPlaceWindow
  811. (
  812.     int x,
  813.     int y
  814. )
  815. {
  816.     BOOL    fVisible;
  817.     HRESULT hr;
  818.     DWORD dwWindowStyle;
  819.  
  820.     // if we've already got a window, do nothing.
  821.     //
  822.     if (m_hwnd)
  823.         return m_hwnd;
  824.  
  825.     // get the user to register the class if it's not already
  826.     // been done.
  827.     //
  828.     if (!CTLWNDCLASSREGISTERED(m_ObjectType)) {
  829.         if (!RegisterClassData())
  830.             return NULL;
  831.         else
  832.             CTLWNDCLASSREGISTERED(m_ObjectType) = TRUE;
  833.     }
  834.  
  835.     // let the user set up things like the window title, the
  836.     // style, and anything else they feel interested in fiddling
  837.     // with.
  838.     //
  839.     BeforeCreateWindow();
  840.  
  841.     dwWindowStyle = m_dwWindowStyle | WS_CHILD | WS_CLIPSIBLINGS;
  842.  
  843.     // create window visible if parent hidden (common case)
  844.     // otherwise, create hidden, then shown.  this is a little subtle, but
  845.     // it makes sense eventually.
  846.     //
  847.     if (!m_hwndParent)
  848.         m_hwndParent = GetParkingWindow();
  849.  
  850.     fVisible = IsWindowVisible(m_hwndParent);
  851.  
  852.     // This one kinda sucks -- if a control is subclassed, and we're in
  853.     // a host that doesn't support Message Reflecting, we have to create
  854.     // the user window in another window which will do all the reflecting.
  855.     // VERY blech. [don't however, bother in design mode]
  856.     //
  857.     if (SUBCLASSWNDPROCOFCONTROL(m_ObjectType) && (m_hwndParent != GetParkingWindow())) {
  858.         // determine if the host supports message reflecting.
  859.         //
  860.         if (!m_fCheckedReflecting) {
  861.             VARIANT_BOOL f;
  862.             hr = GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, VT_BOOL, &f);
  863.             if (FAILED(hr) || !f)
  864.                 m_fHostReflects = FALSE;
  865.             m_fCheckedReflecting = TRUE;
  866.         }
  867.  
  868.         // if the host doesn't support reflecting, then we have to create
  869.         // an extra window around the control window, and then parent it
  870.         // off that.
  871.         //
  872.         if (!m_fHostReflects) {
  873.             ASSERT(m_hwndReflect == NULL, "Blood Spewing Maggots! Where'd this come from?");
  874.             m_hwndReflect = CreateReflectWindow(!fVisible, m_hwndParent, x, y, &m_Size);
  875.             if (!m_hwndReflect)
  876.                 return NULL;
  877.             SetWindowLong(m_hwndReflect, GWL_USERDATA, (long)this);
  878.             dwWindowStyle |= WS_VISIBLE;
  879.         }
  880.     } else {
  881.         if (!fVisible)
  882.             dwWindowStyle |= WS_VISIBLE;
  883.     }
  884.  
  885.     s_pLastControlCreated = this;
  886.     m_fCreatingWindow = TRUE;
  887.  
  888.     // finally, go create the window, parenting it as appropriate.
  889.     //
  890.     m_hwnd = CreateWindowEx(m_dwWindowExStyle, WNDCLASSNAMEOFCONTROL(m_ObjectType),
  891.                             m_szWindowTitle,
  892.                             dwWindowStyle,
  893.                             (m_hwndReflect) ? 0 : x,
  894.                             (m_hwndReflect) ? 0 : y,
  895.                             m_Size.cx, m_Size.cy,
  896.                             (m_hwndReflect) ? m_hwndReflect : m_hwndParent,
  897.                             NULL, g_hInstance, NULL);
  898.  
  899.     m_fCreatingWindow = FALSE;
  900.     s_pLastControlCreated = NULL;
  901.  
  902.     if (m_hwnd) {
  903.         // let the derived-control do something if they so desire
  904.         //
  905.         AfterCreateWindow();
  906.  
  907.         // if we didn't create the window visible, show it now.
  908.         //
  909.         if (fVisible)
  910.             ShowWindow(GetOuterWindow(), SW_SHOW);
  911.     }
  912.  
  913.     return m_hwnd;
  914. }
  915.  
  916.  
  917.  
  918. //=--------------------------------------------------------------------------=
  919. // COleControl::SetInPlaceParent    [helper]
  920. //=--------------------------------------------------------------------------=
  921. // sets up the parent window for our control.
  922. //
  923. // Parameters:
  924. //    HWND            - [in] new parent window
  925. //
  926. // Notes:
  927. //
  928. void COleControl::SetInPlaceParent
  929. (
  930.     HWND hwndParent
  931. )
  932. {
  933.     if (m_hwndParent == hwndParent)
  934.         return;
  935.  
  936.     m_hwndParent = hwndParent;
  937.     if (m_hwnd)
  938.         SetParent(GetOuterWindow(), hwndParent);
  939. }
  940.  
  941. //=--------------------------------------------------------------------------=
  942. // COleControl::ControlWindowProc
  943. //=--------------------------------------------------------------------------=
  944. // default window proc for an OLE Control.   controls will have their own
  945. // window proc called from this one, after some processing is done.
  946. //
  947. // Parameters:
  948. //    - see win32sdk docs.
  949. //
  950. // Notes:
  951. //
  952. LRESULT CALLBACK COleControl::ControlWindowProc
  953. (
  954.     HWND    hwnd,
  955.     UINT    msg,
  956.     WPARAM  wParam,
  957.     LPARAM  lParam
  958. )
  959. {
  960.     COleControl *pCtl = ControlFromHwnd(hwnd);
  961.     HRESULT hr;
  962.     LRESULT lResult;
  963.     DWORD   dwCookie;
  964.  
  965.     // if the value isn't a positive value, then it's in some special
  966.     // state [creation or destruction]  this is safe because under win32,
  967.     // the upper 2GB of an address space aren't available.
  968.     //
  969.     if ((LONG)pCtl == 0) {
  970.         pCtl = s_pLastControlCreated;
  971.         SetWindowLong(hwnd, GWL_USERDATA, (LONG)pCtl);
  972.         pCtl->m_hwnd = hwnd;
  973.     } else if ((ULONG)pCtl == 0xffffffff) {
  974.         return DefWindowProc(hwnd, msg, wParam, lParam);
  975.     }
  976.  
  977.     // message preprocessing
  978.     //
  979.     if (pCtl->m_pSimpleFrameSite) {
  980.         hr = pCtl->m_pSimpleFrameSite->PreMessageFilter(hwnd, msg, wParam, lParam, &lResult, &dwCookie);
  981.         if (hr == S_FALSE) return lResult;
  982.     }
  983.  
  984.     // for certain messages, do not call the user window proc. instead,
  985.     // we have something else we'd like to do.
  986.     //
  987.     switch (msg) {
  988.       case WM_PAINT:
  989.         {
  990.         // call the user's OnDraw routine.
  991.         //
  992.         PAINTSTRUCT ps;
  993.         RECT        rc;
  994.         HDC         hdc;
  995.  
  996.         // if we're given an HDC, then use it
  997.         //
  998.         if (!wParam)
  999.             hdc = BeginPaint(hwnd, &ps);
  1000.         else
  1001.             hdc = (HDC)wParam;
  1002.  
  1003.         GetClientRect(hwnd, &rc);
  1004.         pCtl->OnDraw(hdc, (RECTL *)&rc, NULL, NULL);
  1005.  
  1006.         if (!wParam)
  1007.             EndPaint(hwnd, &ps);
  1008.         }
  1009.         break;
  1010.  
  1011.       default:
  1012.         // call the derived-control's window proc
  1013.         //
  1014.         lResult = pCtl->WindowProc(hwnd, msg, wParam, lParam);
  1015.         break;
  1016.     }
  1017.  
  1018.     // message postprocessing
  1019.     //
  1020.     switch (msg) {
  1021.  
  1022.       case WM_NCDESTROY:
  1023.         // after this point, the window doesn't exist any more
  1024.         //
  1025.         pCtl->m_hwnd = NULL;
  1026.         break;
  1027.  
  1028.       case WM_SETFOCUS:
  1029.       case WM_KILLFOCUS:
  1030.         // give the control site focus notification
  1031.         //
  1032.         if (pCtl->m_fInPlaceActive && pCtl->m_pControlSite)
  1033.             pCtl->m_pControlSite->OnFocus(msg == WM_SETFOCUS);
  1034.         break;
  1035.  
  1036.       case WM_SIZE:
  1037.         // a change in size is a change in view
  1038.         //
  1039.         if (!pCtl->m_fCreatingWindow)
  1040.             pCtl->ViewChanged();
  1041.         break;
  1042.     }
  1043.  
  1044.     // lastly, simple frame postmessage processing
  1045.     //
  1046.     if (pCtl->m_pSimpleFrameSite)
  1047.         pCtl->m_pSimpleFrameSite->PostMessageFilter(hwnd, msg, wParam, lParam, &lResult, dwCookie);
  1048.  
  1049.     return lResult;
  1050. }
  1051.  
  1052. //=--------------------------------------------------------------------------=
  1053. // COleControl::ReflectWindowProc
  1054. //=--------------------------------------------------------------------------=
  1055. // reflects window messages on to the child window.  very lame.
  1056. //
  1057. // Parameters and Output:
  1058. //    - see win32 sdk docs
  1059. //
  1060. // Notes:
  1061. //
  1062. LRESULT CALLBACK COleControl::ReflectWindowProc
  1063. (
  1064.     HWND    hwnd,
  1065.     UINT    msg,
  1066.     WPARAM  wParam,
  1067.     LPARAM  lParam
  1068. )
  1069. {
  1070.     COleControl *pCtl;
  1071.  
  1072.     switch (msg) {
  1073.         case WM_COMMAND:
  1074.         case WM_NOTIFY:
  1075.         case WM_CTLCOLORBTN:
  1076.         case WM_CTLCOLORDLG:
  1077.         case WM_CTLCOLOREDIT:
  1078.         case WM_CTLCOLORLISTBOX:
  1079.         case WM_CTLCOLORMSGBOX:
  1080.         case WM_CTLCOLORSCROLLBAR:
  1081.         case WM_CTLCOLORSTATIC:
  1082.         case WM_DRAWITEM:
  1083.         case WM_MEASUREITEM:
  1084.         case WM_DELETEITEM:
  1085.         case WM_VKEYTOITEM:
  1086.         case WM_CHARTOITEM:
  1087.         case WM_COMPAREITEM:
  1088.         case WM_HSCROLL:
  1089.         case WM_VSCROLL:
  1090.         case WM_PARENTNOTIFY:
  1091.         case WM_SETFOCUS:
  1092.         case WM_SIZE:
  1093.             pCtl = (COleControl *)GetWindowLong(hwnd, GWL_USERDATA);
  1094.             if (pCtl)
  1095.                 return SendMessage(pCtl->m_hwnd, OCM__BASE + msg, wParam, lParam);
  1096.             break;
  1097.     }
  1098.  
  1099.     return DefWindowProc(hwnd, msg, wParam, lParam);
  1100. }
  1101.  
  1102. //=--------------------------------------------------------------------------=
  1103. // COleControl::GetAmbientProperty    [callable]
  1104. //=--------------------------------------------------------------------------=
  1105. // returns the value of an ambient property
  1106. //
  1107. // Parameters:
  1108. //    DISPID        - [in]  property to get
  1109. //    VARTYPE       - [in]  type of desired data
  1110. //    void *        - [out] where to put the data
  1111. //
  1112. // Output:
  1113. //    BOOL          - FALSE means didn't work.
  1114. //
  1115. // Notes:
  1116. //
  1117. BOOL COleControl::GetAmbientProperty
  1118. (
  1119.     DISPID  dispid,
  1120.     VARTYPE vt,
  1121.     void   *pData
  1122. )
  1123. {
  1124.     DISPPARAMS dispparams;
  1125.     VARIANT v, v2;
  1126.     HRESULT hr;
  1127.  
  1128.     v.vt = VT_EMPTY;
  1129.     v.lVal = 0;
  1130.     v2.vt = VT_EMPTY;
  1131.     v.lVal = 0;
  1132.  
  1133.     // get a pointer to the source of ambient properties.
  1134.     //
  1135.     if (!m_pDispAmbient) {
  1136.         if (m_pClientSite)
  1137.             m_pClientSite->QueryInterface(IID_IDispatch, (void **)&m_pDispAmbient);
  1138.  
  1139.         if (!m_pDispAmbient)
  1140.             return FALSE;
  1141.     }
  1142.  
  1143.     // now go and get the property into a variant.
  1144.     //
  1145.     memset(&dispparams, 0, sizeof(DISPPARAMS));
  1146.     hr = m_pDispAmbient->Invoke(dispid, IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams,
  1147.                                 &v, NULL, NULL);
  1148.     if (FAILED(hr)) return FALSE;
  1149.  
  1150.     // we've got the variant, so now go an coerce it to the type that the user
  1151.     // wants.  if the types are the same, then this will copy the stuff to
  1152.     // do appropriate ref counting ...
  1153.     //
  1154.     hr = VariantChangeType(&v2, &v, 0, vt);
  1155.     if (FAILED(hr)) {
  1156.         VariantClear(&v);
  1157.         return FALSE;
  1158.     }
  1159.  
  1160.     // copy the data to where the user wants it
  1161.     //
  1162.     CopyMemory(pData, &(v2.lVal), g_rgcbDataTypeSize[vt]);
  1163.     VariantClear(&v);
  1164.     return TRUE;
  1165. }
  1166.  
  1167. //=--------------------------------------------------------------------------=
  1168. // COleControl::GetAmbientFont    [callable]
  1169. //=--------------------------------------------------------------------------=
  1170. // gets the current font for the user.
  1171. //
  1172. // Parameters:
  1173. //    IFont **         - [out] where to put the font.
  1174. //
  1175. // Output:
  1176. //    BOOL             - FALSE means couldn't get it.
  1177. //
  1178. // Notes:
  1179. //
  1180. BOOL COleControl::GetAmbientFont
  1181. (
  1182.     IFont **ppFont
  1183. )
  1184. {
  1185.     IDispatch *pFontDisp;
  1186.  
  1187.     // we don't have to do much here except get the ambient property and QI
  1188.     // it for the user.
  1189.     //
  1190.     *ppFont = NULL;
  1191.     if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pFontDisp))
  1192.         return FALSE;
  1193.  
  1194.     pFontDisp->QueryInterface(IID_IFont, (void **)ppFont);
  1195.     pFontDisp->Release();
  1196.     return (*ppFont) ? TRUE : FALSE;
  1197. }
  1198.  
  1199. //=--------------------------------------------------------------------------=
  1200. // COleControl::DesignMode
  1201. //=--------------------------------------------------------------------------=
  1202. // returns TRUE if we're in Design mode.
  1203. //
  1204. // Output:
  1205. //    BOOL            - true is design mode, false is run mode
  1206. //
  1207. // Notes:
  1208. //
  1209. BOOL COleControl::DesignMode
  1210. (
  1211.     void
  1212. )
  1213. {
  1214.     // if we don't already know our run mode, go and get it.  we'll assume
  1215.     // it's true unless told otherwise [or if the operation fails ...]
  1216.     //
  1217.     if (!m_fModeFlagValid) {
  1218.         m_fModeFlagValid = TRUE;
  1219.         m_fRunMode = TRUE;
  1220.         GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &m_fRunMode);
  1221.     }
  1222.  
  1223.     return !m_fRunMode;
  1224. }
  1225.  
  1226.  
  1227. //=--------------------------------------------------------------------------=
  1228. // COleControl::FireEvent
  1229. //=--------------------------------------------------------------------------=
  1230. // fires an event.  handles arbitrary number of arguments.
  1231. //
  1232. // Parameters:
  1233. //    EVENTINFO *        - [in] struct that describes the event.
  1234. //    ...                - arguments to the event
  1235. //
  1236. // Output:
  1237. //    none
  1238. //
  1239. // Notes:
  1240. //    - use stdarg's va_* macros.
  1241. //
  1242. void __cdecl COleControl::FireEvent
  1243. (
  1244.     EVENTINFO *pEventInfo,
  1245.     ...
  1246. )
  1247. {
  1248.     va_list    valist;
  1249.     DISPPARAMS dispparams;
  1250.     VARIANT    rgvParameters[MAX_ARGS];
  1251.     VARIANT   *pv;
  1252.     VARTYPE    vt;
  1253.     int        iParameter;
  1254.     int        cbSize;
  1255.  
  1256.     ASSERT(pEventInfo->cParameters <= MAX_ARGS, "Don't support more than MAX_ARGS params.  sorry.");
  1257.  
  1258.     va_start(valist, pEventInfo);
  1259.  
  1260.     // copy the Parameters into the rgvParameters array.  make sure we reverse
  1261.     // them for automation
  1262.     //
  1263.     pv = &(rgvParameters[pEventInfo->cParameters - 1]);
  1264.     for (iParameter = 0; iParameter < pEventInfo->cParameters; iParameter++) {
  1265.  
  1266.         vt = pEventInfo->rgTypes[iParameter];
  1267.  
  1268.         // if it's a by value variant, then just copy the whole
  1269.         // dang thing
  1270.         //
  1271.         if (vt == VT_VARIANT)
  1272.             *pv = va_arg(valist, VARIANT);
  1273.         else {
  1274.             // copy the vt and the data value.
  1275.             //
  1276.             pv->vt = vt;
  1277.             if (vt & VT_BYREF)
  1278.                 cbSize = sizeof(void *);
  1279.             else
  1280.                 cbSize = g_rgcbDataTypeSize[vt];
  1281.  
  1282.             // small optimization -- we can copy 2/4 bytes over quite
  1283.             // quickly.
  1284.             //
  1285.             if (cbSize == sizeof(short))
  1286.                 V_I2(pv) = va_arg(valist, short);
  1287.             else if (cbSize == 4)
  1288.                 V_I4(pv) = va_arg(valist, long);
  1289.             else {
  1290.                 // copy over 8 bytes
  1291.                 //
  1292.                 ASSERT(cbSize == 8, "D'oH! don't recognize the type!!");
  1293.                 V_CY(pv) = va_arg(valist, CURRENCY);
  1294. #if 0
  1295.                 // convert doubles back to floats
  1296.                 //
  1297.                 if (vt == VT_R4)
  1298.                     pv->fltVal = (float)pv->dblVal;
  1299. #endif // 0
  1300.             }
  1301.         }
  1302.  
  1303.         pv--;
  1304.     }
  1305.  
  1306.     // fire the event
  1307.     //
  1308.     dispparams.rgvarg = rgvParameters;
  1309.     dispparams.cArgs = pEventInfo->cParameters;
  1310.     dispparams.rgdispidNamedArgs = NULL;
  1311.     dispparams.cNamedArgs = 0;
  1312.  
  1313.     m_cpEvents.DoInvoke(pEventInfo->dispid, &dispparams);
  1314.  
  1315.     va_end(valist);
  1316. }
  1317.  
  1318. //=--------------------------------------------------------------------------=
  1319. // COleControl::AfterCreateWindow    [overridable]
  1320. //=--------------------------------------------------------------------------=
  1321. // something the user can pay attention to
  1322. //
  1323. // Notes:
  1324. //
  1325. void COleControl::AfterCreateWindow
  1326. (
  1327.     void
  1328. )
  1329. {
  1330.     // do nothing
  1331. }
  1332.  
  1333.  
  1334. //=--------------------------------------------------------------------------=
  1335. // COleControl::InvalidateControl    [callable]
  1336. //=--------------------------------------------------------------------------=
  1337. void COleControl::InvalidateControl(LPCRECT lpRect)
  1338. {
  1339.     if (m_fInPlaceActive)
  1340.         InvalidateRect(m_hwnd, lpRect, TRUE);
  1341.     else
  1342.         ViewChanged();
  1343.  
  1344.     // CONSIDER: one might want to call pOleAdviseHolder->OnDataChanged() here
  1345.     // if there was support for IDataObject
  1346. }
  1347.  
  1348. //=--------------------------------------------------------------------------=
  1349. // COleControl::SetControlSize    [callable]
  1350. //=--------------------------------------------------------------------------=
  1351. // sets the control size. they'll give us the size in pixels.  we've got to
  1352. // convert them back to HIMETRIC before passing them on!
  1353. //
  1354. // Parameters:
  1355. //    SIZEL *        - [in] new size
  1356. //
  1357. // Output:
  1358. //    BOOL
  1359. //
  1360. // Notes:
  1361. //
  1362. BOOL COleControl::SetControlSize
  1363. (
  1364.     SIZEL *pSize
  1365. )
  1366. {
  1367.     HRESULT hr;
  1368.     SIZEL slHiMetric;
  1369.  
  1370.     PixelToHiMetric(pSize, &slHiMetric);
  1371.     hr = SetExtent(DVASPECT_CONTENT, &slHiMetric);
  1372.     return (FAILED(hr)) ? FALSE : TRUE;
  1373. }
  1374.  
  1375. //=--------------------------------------------------------------------------=
  1376. // COleControl::RecreateControlWindow    [callable]
  1377. //=--------------------------------------------------------------------------=
  1378. // called by a [subclassed, typically] control to recreate it's control
  1379. // window.
  1380. //
  1381. // Parameters:
  1382. //    none
  1383. //
  1384. // Output:
  1385. //    HRESULT
  1386. //
  1387. // Notes:
  1388. //    - NOTE: USE ME EXTREMELY SPARINGLY! THIS IS AN EXTREMELY EXPENSIVE
  1389. //      OPERATION!
  1390. //
  1391. HRESULT COleControl::RecreateControlWindow
  1392. (
  1393.     void
  1394. )
  1395. {
  1396.     HRESULT hr;
  1397.  
  1398.     // if we're in place active, then we have to deactivate, and reactivate
  1399.     // ourselves with the new window ...
  1400.     //
  1401.     if (m_fInPlaceActive) {
  1402.  
  1403.         hr = InPlaceDeactivate();
  1404.         RETURN_ON_FAILURE(hr);
  1405.         hr = InPlaceActivate((m_fUIActive) ? OLEIVERB_UIACTIVATE : OLEIVERB_INPLACEACTIVATE);
  1406.         RETURN_ON_FAILURE(hr);
  1407.  
  1408.     } else if (m_hwnd) {
  1409.         DestroyWindow(m_hwnd);
  1410.         m_hwnd = NULL;
  1411.         if (m_hwndReflect) {
  1412.             DestroyWindow(m_hwndReflect);
  1413.             m_hwndReflect = NULL;
  1414.         }
  1415.  
  1416.         CreateInPlaceWindow(0, 0);
  1417.     }
  1418.  
  1419.     return m_hwnd ? S_OK : E_FAIL;
  1420. }
  1421.  
  1422.  
  1423. // from Globals.C
  1424. //
  1425. extern HINSTANCE g_hInstResources;
  1426.  
  1427. //=--------------------------------------------------------------------------=
  1428. // COleControl::GetResourceHandle    [callable]
  1429. //=--------------------------------------------------------------------------=
  1430. // gets the HINSTANCE of the DLL where the control should get resources
  1431. // from.  implemented in such a way to support satellite DLLs.
  1432. //
  1433. // Output:
  1434. //    HINSTANCE
  1435. //
  1436. // Notes:
  1437. //
  1438. HINSTANCE COleControl::GetResourceHandle
  1439. (
  1440.     void
  1441. )
  1442. {
  1443.     if (!g_fSatelliteLocalization)
  1444.         return g_hInstance;
  1445.  
  1446.     // if we've already got it, then there's not all that much to do.
  1447.     //
  1448.     if (g_hInstResources)
  1449.         return g_hInstResources;
  1450.  
  1451.     // we'll get the ambient localeid from the host, and pass that on to the
  1452.     // automation object.
  1453.     //
  1454.     if (!g_fHaveLocale)
  1455.         if (!GetAmbientProperty(DISPID_AMBIENT_LOCALEID, VT_I4, &g_lcidLocale))
  1456.             return NULL;
  1457.  
  1458.     g_fHaveLocale = TRUE;
  1459.     return ::GetResourceHandle();
  1460. }
  1461.  
  1462.  
  1463.